﻿/***********************************************************************************************
 * 
 * ProjectName: WMSSoft.Lib.WinKStart
 * 
 * Description: Read all Functions from Disk and and create an instance
 * 
 * Created:     08.09.2014
 * 
 * Author:      matthias wagler - matthias@WMSSoft.de
 * 
 * Copyright:   Copyright 2012 by WMSSoft.net
 * 
 * License:     GPLv3
 * 
 * History:     0.09.2014 - matthias wagler matthias@WMSSoft.de   -   Created
 * 
 **********************************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using WMSSoft.Lib.Basic;
using WMSSoft.Lib.Const;
using WMSSoft.Lib.Texte;
using WMSSoft.Lib.Interfaces;
using WMSSoft.Lib.WinKStart.Model.MenuConfig;

namespace WMSSoft.Lib.WinKStart
{
    public class cFunctionsReader
    {
        private Dictionary<string, cWinKStartFunction> m_Items = new Dictionary<string, cWinKStartFunction>();
        private Dictionary<string, iWinKStartFunctions> m_ItemInstances = new Dictionary<string, iWinKStartFunctions>();

        #region Properties
        public Dictionary<string, cWinKStartFunction> Item
        {
            get { return m_Items; }
        }

        public Dictionary<string, iWinKStartFunctions> ItemInstances
        {
            get { return m_ItemInstances; }
        }
        #endregion

        #region Public Methods
        public void Load(System.Xml.XmlNode Node)
        {
            try
            {
                //Remove all existing items from list
                m_Items.Clear();
                m_ItemInstances.Clear();

                if (Node != null)
                {
                    //first read all DataSources Attributes

                    if (Node.ChildNodes.Count > 0)
                    {
                        cWinKStartFunction ChildItem = null;
                  
                        //Load ex child and create a DataSourceItem
                        foreach (System.Xml.XmlNode SubNode in Node.ChildNodes)
                        {
                            if (SubNode.Name == XMLNodeNames.MENUCONFIG_XMLNODE_SUBNODE__ADDFUNCTION)
                            {
                                ChildItem = ProcessLoad_Function(SubNode);
                                //add function
                                if (ChildItem != null) m_Items.Add(ChildItem.Name, ChildItem);
                            }                            
                        }
                        //Init installed Functions
                        InitFunctionItems();
                    }
                }
            }
            catch (Exception Ex)
            {
                throw new Exception(LanguageStrings.GetText(ErrorMessages.FUNCTION_READER__ERROR_UNABLE_TO_LOAD_FUNCTION_CONFIG), Ex);
            }
        }

        /// <summary>
        /// Close the Code in Function Assemblies
        /// </summary>
        public void Unload()
        {
            try
            {
                Dictionary<string, cWinKStartFunction>.KeyCollection tmpKeys = m_Items.Keys;
                foreach (string KeyItem in tmpKeys)
                {
                    if (m_ItemInstances.ContainsKey(KeyItem) == true)
                    {
                        m_ItemInstances[KeyItem].Destroy();
                    }
                }
            }
            catch (Exception Ex)
            {

            }
        }
        #endregion

        #region Private Methods

        cWinKStartFunction ProcessLoad_Function(System.Xml.XmlNode Item)
        {
            try
            {
                if (Item != null)
                {
                    cWinKStartFunction tmpFunction = new cWinKStartFunction();
                    //Load Name Attribute
                    if (Item.Attributes[XMLNodeNames.DATASOURCE_XMLNODE_ATTRIBUTE__NAME] != null)
                    {
                        tmpFunction.Name = Item.Attributes[XMLNodeNames.DATASOURCE_XMLNODE_ATTRIBUTE__NAME].Value;
                    }
                    else throw new Exception(LanguageStrings.GetText(ErrorMessages.FUNCTION_READER__ERROR_NO_NAME));
                    //Load Assembly Attribute
                    if (Item.Attributes[XMLNodeNames.DATASOURCE_XMLNODE_ATTRIBUTE__ASSEMBLY] != null)
                    {
                        tmpFunction.Assembly = Item.Attributes[XMLNodeNames.DATASOURCE_XMLNODE_ATTRIBUTE__ASSEMBLY].Value;
                    }
                    else throw new Exception(LanguageStrings.GetText(ErrorMessages.FUNCTION_READER__ERROR_NO_ASSEMBLY));
                    //Load ClassName Attribute
                    if (Item.Attributes[XMLNodeNames.DATASOURCE_XMLNODE_ATTRIBUTE__CLASSNAME] != null)
                    {
                        tmpFunction.ClassName = Item.Attributes[XMLNodeNames.DATASOURCE_XMLNODE_ATTRIBUTE__CLASSNAME].Value;
                    }
                    else throw new Exception(LanguageStrings.GetText(ErrorMessages.FUNCTION_READER__ERROR_NO_CLASSNAME));
                    //Load DataSource Attribute
                    if (Item.Attributes[XMLNodeNames.MENUCONFIG_XMLNODE_ATTRIBUTE__DATASOURCE] != null)
                    {
                        tmpFunction.DataSource = Item.Attributes[XMLNodeNames.MENUCONFIG_XMLNODE_ATTRIBUTE__DATASOURCE].Value;
                    }
                    else throw new Exception(LanguageStrings.GetText(ErrorMessages.FUNCTION_READER__ERROR_NO_DATASOURCE));
                    //Load Filter Attribute
                    if (Item.Attributes[XMLNodeNames.MENUCONFIG_XMLNODE_ATTRIBUTE__FILTER] != null)
                    {
                        tmpFunction.Filter = Item.Attributes[XMLNodeNames.MENUCONFIG_XMLNODE_ATTRIBUTE__FILTER].Value;
                    }

                    //Load Function Options
                    foreach (System.Xml.XmlNode ChildNode in Item.ChildNodes)
                    {
                        if (ChildNode.Name == XMLNodeNames.MENUCONFIG_XMLNODE_SUBNODE__OPTIONS)
                        {
                            foreach (System.Xml.XmlNode SubItem in ChildNode.ChildNodes)
                            {
                                KeyValueAssignment KeyValueItem = cMenuConfigReader.CreateKeyValueAssignmentFromXML(SubItem);
                                tmpFunction.Options.Add(KeyValueItem.Key.ToUpper(), KeyValueItem);
                            }
                        }
                    }

                    return tmpFunction;
                }
                else throw new Exception(LanguageStrings.GetText(ErrorMessages.FUNCTION_READER__ERROR_NO_FUNCTION_NODE));
            }
            catch (Exception Ex)
            {
                throw new Exception(LanguageStrings.GetText(ErrorMessages.FUNCTION_READER__ERROR_WRONG_FUNCTION_CONFIGURATION), Ex);
            }
        }

        void InitFunctionItems()
        {
            try
            {
                Dictionary<string, cWinKStartFunction>.KeyCollection tmpKeys = m_Items.Keys;
                foreach (string KeyItem in tmpKeys)
                {
                    if (m_Items.ContainsKey(KeyItem) == true)
                    {
                        iWinKStartFunctions tmpFunctionInstance = null;
                        tmpFunctionInstance = InstanceFunction(m_Items[KeyItem]);
                        if (tmpFunctionInstance != null)
                        {
                            if (m_ItemInstances.ContainsKey(KeyItem) == false)
                                m_ItemInstances.Add(KeyItem, tmpFunctionInstance);
                            else
                                m_ItemInstances[KeyItem] = tmpFunctionInstance;
                        }
                    }
                }
            }
            catch (Exception Ex)
            {
                CMessagelogging.AppendMessage("Unable to Init Functions", Ex, true, EMessageTypes.Error);
            }
        }

        iWinKStartFunctions InstanceFunction(cWinKStartFunction Data)
        {
            try
            {
                string tmpFunctionPath = System.IO.Path.Combine(cUserSettingsReader.FunctionsPaths, Data.Assembly);
                if (System.IO.File.Exists(tmpFunctionPath) == true)
                {
                    System.Reflection.Assembly tmpAssembly = System.Reflection.Assembly.LoadFile(tmpFunctionPath);

                    iWinKStartFunctions tmpDSInstance = (iWinKStartFunctions)tmpAssembly.CreateInstance(Data.ClassName);
                    if (tmpDSInstance != null)
                    {
                        //Initialise Function
                        tmpDSInstance.Init();
                    }
                    return tmpDSInstance;

                }
                else throw new Exception(LanguageStrings.GetText(ErrorMessages.FUNCTION_READER__ERROR_UNABLE_TO_LOAD_FUNCTION_ASSEMBLY_ASSEMBLY_DOES_NOT_EXIST));
            }
            catch (Exception Ex)
            {
                string sMsg = LanguageStrings.GetText(ErrorMessages.FUNCTION_READER__ERROR_UNABLE_TO_LOAD_FUNCTION_ASSEMBLY);
                if (Data != null)
                    sMsg = sMsg.Replace("##FUNCTIONNAME##", Data.Name);
                else
                    sMsg = sMsg.Replace("##FUNCTIONNAME##", "Unknown");
                throw new Exception(sMsg, Ex);
            }
        }
        #endregion
    }
}
